﻿using System.Collections.Generic;
using System.Linq;
using System.Text;
using DimensionsHelper.Common.Contracts.TableFormatter;
using DimensionsHelper.Common.Contracts.TableFormatter.Options;
using DimensionsHelper.Common.Contracts.Excel;
using DimensionsHelper.Common.Contracts.Table;

namespace DimensionsHelper.Services.TableFormatter;

internal class TableMenuBuilder
{
    private readonly string _baseFeature;

    private readonly MenuOptions _options;
    private int _indexLabelCol;
    private int _indexSheetRow;

    private IExcelWorksheetOperator? _indexSheet;
    private IExcelWorksheetOperator? _linkSheet;
    private IExcelWorkbookOperator? _workbook;

    private int _linkSheetRow;
    private bool _prepared;
    private int _tablesCount;

    private IExcelWorksheetOperator IndexSheet => _indexSheet!;
        
    private IExcelWorksheetOperator LinkSheet => _linkSheet!;
        

    internal TableMenuBuilder(IExcelWorkbookOperator workbook, TableFormatterOptions options)
    {
        _options = options.Menu;
        _workbook = workbook;
        _baseFeature = options.Table.BaseFeature;

        _prepared = false;

        if (_options.BuildMenu)
        {
            PrepareMenuSheet();
        }

        _tablesCount = 1;

        _linkSheetRow = 1;
        _indexSheetRow = 1;
        _indexLabelCol = 0;
    }

    private class SheetIndexRanges
    {
        public List<IExcelRangeOperator> TableNumberRanges { get; } = new List<IExcelRangeOperator>();

        public List<IExcelRangeOperator> TableLabelRanges { get; } = new List<IExcelRangeOperator>();

        public List<IExcelRangeOperator> TableBaseRanges { get; } = new List<IExcelRangeOperator>();
    }


    private int _tableRangeStartRow;
    private SheetIndexRanges _sheetRanges = new();


    private void SetSheetIndexRangeStyle()
    {
        CacheRanges();

        // Table label
        foreach (var range in _sheetRanges.TableLabelRanges)
        {
            if (_options.HideNumber)
            {
                // 跳过字体样式，只设置字号
                range.FontSize = _options.TableLabelStyleOptions.Font.FontSize;
                range.SetRangeStyleExceptFontStyle(_options.TableLabelStyleOptions);
            }
            else
            {
                range.SetStyle(_options.TableLabelStyleOptions);
            }
        }

        // Table base
        foreach (var range in _sheetRanges.TableBaseRanges)
        {
            range.SetStyle(_options.BaseStyleOptions);
        }

        // Table number
        foreach (var range in _sheetRanges.TableNumberRanges)
        {
            // 跳过字体样式，只设置字号
            range.FontSize = _options.TableNumberStyleOptions.Font.FontSize;
            range.SetRangeStyleExceptFontStyle(_options.TableNumberStyleOptions);
        }

        _tableRangeStartRow = 0;
        _sheetRanges = new SheetIndexRanges();
    }


    private void PrepareMenuSheet()
    {
        _linkSheet = _workbook!.GetWorksheet(_options.LinkSheetName);
        var linkLabelRange = _linkSheet.GetRange(1, 1);
        linkLabelRange.Value = _options.LinkSheetLabel;
        linkLabelRange.SetStyle(_options.LinkSheetLabelStyleOptions);

        if (_options.MenuType != MenuType.SingleLinkSheet)
        {
            _indexSheet = _workbook.GetWorksheet(_options.IndexSheetName);
        }

        _indexSheet?.MoveToStart();
        _linkSheet.MoveToStart();

        _prepared = true;
    }

    private bool CheckPrepared()
    {
        if (_options.BuildMenu && !_prepared)
        {
            PrepareMenuSheet();
        }

        return _prepared;
    }

    private IExcelRangeOperator GetIndexNumberCell()
    {
        return IndexSheet.GetRange(_indexSheetRow, _indexLabelCol - 1);
    }

    private IExcelRangeOperator GetIndexLabelCell()
    {
        return IndexSheet.GetRange(_indexSheetRow, _indexLabelCol);
    }

    private IExcelRangeOperator GetLinkSheetLabelCell()
    {
        return LinkSheet.GetRange(_linkSheetRow, 2);
    }

    private IExcelRangeOperator GetLinkTableLabelCell()
    {
        return LinkSheet.GetRange(_linkSheetRow, 3);
    }

    internal void StartWorksheet(IExcelWorksheetOperator worksheet)
    {
        if (!CheckPrepared())
        {
            return;
        }

        SetSheetIndexRangeStyle();

        if (!GetLinkSheetLabelCell().IsEmpty())
        {
            _linkSheetRow++;
        }

        var sheetBackCell = worksheet.GetRange(1, 1);
        sheetBackCell.Value = _options.BackText;
        sheetBackCell.SetStyle(_options.BackStyleOptions);

        var sheetLinkCell = GetLinkSheetLabelCell();
        sheetLinkCell.Value = worksheet.Name;

        _tablesCount = 1;

        if (_options.MenuType == MenuType.Regular)
        {
            _indexSheetRow = 2 + _options.EmptyRowsFollowSheetLabel;
            _indexLabelCol += 2;

            if (_options.HideNumber)
            {
                _indexLabelCol--;
            }

            // 如果出示基数并且不是第一个表格，则向后移动一列
            if (_options.ShowBase && _linkSheetRow > 1)
            {
                _indexLabelCol++;
            }

            if (!_options.HideNumber)
            {
                var indexBackCell = IndexSheet.GetRange(1, _indexLabelCol - 1);
                indexBackCell.Value = _options.BackText;
                indexBackCell.SetStyle(_options.BackStyleOptions);
                indexBackCell.SetHyperlink(sheetLinkCell);
            }

            var indexLabelCell = IndexSheet.GetRange(1, _indexLabelCol);
            indexLabelCell.Value = worksheet.Name;
            indexLabelCell.SetStyle(_options.SheetLabelStyleOptions);
            sheetBackCell.SetHyperlink(indexLabelCell);

            if (_options.HideNumber)
            {
                indexLabelCell.SetHyperlink(sheetLinkCell);
            }

            sheetLinkCell.SetHyperlink(indexLabelCell);
        }
        else
        {
            sheetLinkCell.SetStyle(_options.SheetLabelStyleOptions);
            sheetBackCell.SetHyperlink(sheetLinkCell);
            sheetLinkCell.SetHyperlink(sheetBackCell);
        }
    }


    private void CacheRanges()
    {
        if (_tableRangeStartRow == 0)
        {
            return;
        }

        if (!_options.HideNumber)
        {
            _sheetRanges.TableNumberRanges.Add(IndexSheet.GetRange(_tableRangeStartRow,
                _indexLabelCol - 1,
                _indexSheetRow - 1,
                _indexLabelCol));
        }

        _sheetRanges.TableLabelRanges.Add(IndexSheet.GetRange(_tableRangeStartRow,
            _indexLabelCol,
            _indexSheetRow - 1,
            _indexLabelCol));

        if (_options.ShowBase)
        {
            _sheetRanges.TableBaseRanges.Add(IndexSheet.GetRange(_tableRangeStartRow,
                _indexLabelCol + 1,
                _indexSheetRow - 1,
                _indexLabelCol + 1));
        }

        _tableRangeStartRow = 0;
    }


    private void WriteSection(string section)
    {
        IExcelRangeOperator fullSectionRange;

        if (_options.MenuType == MenuType.Regular)
        {
            if (_options is { HideNumber: false, MergeSection: true })
            {
                GetIndexNumberCell().Value = section;
            }
            else
            {
                GetIndexLabelCell().Value = section;
            }

            var fromCol = _indexLabelCol;
            var toCol = _indexLabelCol;

            if (!_options.HideNumber)
            {
                fromCol--;
            }

            if (_options.ShowBase)
            {
                toCol++;
            }

            fullSectionRange = IndexSheet.GetRange(_indexSheetRow, fromCol, _indexSheetRow, toCol);
        }
        else
        {
            var labelCell = GetLinkTableLabelCell();
            labelCell.Value = section;

            fullSectionRange = _options.ShowBase 
                ? LinkSheet.GetRange(_linkSheetRow, 3, _linkSheetRow, 4) 
                : LinkSheet.GetRange(_linkSheetRow, 3);
        }

        if (_options.MergeSection)
        {
            fullSectionRange.Merge();
        }

        CacheRanges();
        fullSectionRange.SetStyle(_options.SectionStyleOptions);
    }

    private void WriteTableBase(IExcelWorksheetOperator worksheet, ref int row, int baseCol, ITable table)
    {
        var baseLines = table.Where(line => line.TestLineType(LineType.Base)).ToArray();
        if (baseLines.Length <= 0)
        {
            return;
        }

        var baseText = new StringBuilder();

        for (var i = 0; i < baseLines.Length; i++)
        {
            var bLine = baseLines[i];

            if (bLine.Count < _options.BaseValueColumn || bLine[_options.BaseValueColumn - 1].IsEmpty)
            {
                continue;
            }

            if (baseText.Length > 0 && _options.ShowMultiBaseInOneCell)
            {
                baseText.AppendLine();
            }

            if (string.IsNullOrEmpty(_options.BaseContentFormat))
            {
                baseText.Append(bLine[_options.BaseValueColumn - 1].Text);
            }
            else
            {
                var label = "";

                if (bLine[0].Text.Length > _baseFeature.Length)
                {
                    label = bLine[0].Text[_baseFeature.Length..].Trim();
                }

                baseText.Append(string.Format(_options.BaseContentFormat,
                    bLine[_options.BaseValueColumn - 1].Text, label));
            }

            if (_options.ShowMultiBase &&
                (i != baseLines.Length - 1 || !_options.ShowMultiBaseInOneCell) &&
                _options.ShowMultiBaseInOneCell)
            {
                continue;
            }

            var baseCell = worksheet.GetRange(row, baseCol);
            baseCell.Value = baseText.ToString();

            if (!_options.ShowMultiBase)
            {
                break;
            }

            if (_options.ShowMultiBaseInOneCell)
            {
                continue;
            }

            if (i < baseLines.Length - 1)
            {
                ++row;
            }

            baseText.Clear();
        }
    }

    internal void PushTable(IExcelRangeOperator tableTitleCell, ITable table, string section)
    {
        if (!CheckPrepared())
        {
            return;
        }

        if (!string.IsNullOrEmpty(section) && _options.ShowSection)
        {
            WriteSection(section);
            _indexSheetRow++;
        }

        if (_tableRangeStartRow == 0)
        {
            _tableRangeStartRow = _indexSheetRow;
        }

        if (_options.MenuType == MenuType.Regular)
        {
            if (!_options.HideNumber)
            {
                var numberCell = GetIndexNumberCell();
                numberCell.Value = _tablesCount;
                numberCell.SetHyperlink(tableTitleCell);
            }

            var labelCell = GetIndexLabelCell();
            labelCell.Value = tableTitleCell.Text;
            tableTitleCell.SetHyperlink(labelCell);

            if (_options.HideNumber)
            {
                labelCell.SetHyperlink(tableTitleCell);
            }

            labelCell.SetStyle(_options.TableLabelStyleOptions);

            if (_options.ShowBase)
            {
                WriteTableBase(IndexSheet, ref _indexSheetRow, _indexLabelCol + 1, table);
            }

            _indexSheetRow++;
        }
        else
        {
            var tableLabelCell = GetLinkTableLabelCell();
            tableLabelCell.Value = tableLabelCell.Text;

            if (_options.ShowBase)
            {
                WriteTableBase(LinkSheet, ref _linkSheetRow, 4, table);
            }

            _linkSheetRow++;
        }

        _tablesCount++;
    }

    internal void Finish()
    {
        SetSheetIndexRangeStyle();

        if (_linkSheetRow > 1)
        {
            _linkSheet?.GetRange(1, 2, _linkSheetRow, 2)
                .SetStyle(_options.LinkSheetSheetNameStyleOptions);
        }

        _linkSheet?.AutoFitEntireColumns();
        _indexSheet?.AutoFitEntireColumns();

        _linkSheet = null;
        _indexSheet = null;
        _workbook = null;
    }
}